package com.yincb;

import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.core.Converter;
import org.springframework.stereotype.Component;

import javax.xml.crypto.Data;
import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author yincb
 * @Date 2020/10/20 10:14
 * @Description
 */
public enum BeanCopierWrapper {
    /**
     * 枚举保证BeanCopierWrapper单实例
     */
    BEANCOPIERWRAPPER;
    private Map<String, BeanCopier> cacheBeanCopier;
    BeanCopierWrapper(){
        cacheBeanCopier = cacheBeanCopier == null ? new ConcurrentHashMap<>():cacheBeanCopier;
    }

     /**
     * 获取BeanCopier对象,不使用converter
     * 使用converter字段名和类型相同拷贝，否则不拷贝
     * 使用converter，BeanCopier只使用Converter定义的规则去拷贝属性，所以在convert方法中要考虑所有的属性
     * @param sourceClazz
     * @param targetClazz
     * @param useConverter true:使用converter false:不使用converter
     * @return
     */
    private BeanCopier getBeanCopier(Class sourceClazz, Class targetClazz, boolean useConverter){
        try {
            BeanCopier beanCopier = null;
            String cacheKeySuffix = useConverter ? "useConverter":"noUseConverter";
            String cacheKey = sourceClazz.getName() + targetClazz.getName() + cacheKeySuffix;
            cacheBeanCopier = cacheBeanCopier == null ? new ConcurrentHashMap<>():cacheBeanCopier;
            beanCopier = cacheBeanCopier.get(cacheKey);
            if (beanCopier == null){
                beanCopier = BeanCopier.create(sourceClazz,targetClazz,useConverter);
                cacheBeanCopier.put(cacheKey,beanCopier);
            }
            return beanCopier;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 实体属性拷贝，字段名和类型相同拷贝，否则不拷贝
     * @param source
     * @param target
     */
    public void copyPropertis(Object source,Object target,boolean useConverter){
        try {
            BeanCopier beanCopier = getBeanCopier(source.getClass(), target.getClass(),useConverter);
            if (useConverter){
                beanCopier.copy(source,target,new BeanCopyConverter());
            }else{
                beanCopier.copy(source,target,null);
            }

        } catch (Exception e) {
            throw new RuntimeException("BeanCopierWrapper#copyPropertis error:"+e.getMessage());
        }
    }

    class BeanCopyConverter implements Converter{

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        @Override
        public Object convert(Object source, Class aClass, Object context) {
            if (source instanceof Integer){
                Integer integer = (Integer)source;
                return integer.toString();
            }
            if(source instanceof Date){
                Date date  = (Date)source;
                return sdf.format(date);
            }
            if(source instanceof LocalDate){
                LocalDate localDate = (LocalDate)source;
                return localDate.format(DateTimeFormatter.ISO_DATE);
            }
            if (source instanceof String){
                String str = (String)source;
                return str;
            }
            return null;
        }
    }
}
